Projet Zuul de conception orientée objet en Java d'un jeu d'aventure
Forum des exercices du projet Zuul
Exercice 7.18.6
- Étudiez la documentation du projet suivant (Game, GameEngine, UserInterface,
et Parser) :
zuul-with-images .
- Étudiez maintenant le fichier
zuul-with-images.jar
[ci-joint] pour comprendre son fonctionnement global :
a) Command et CommandWords : pas de changement
b) Room : une méthode supplémentaire, et un attribut supplémentaire ==> modification du constructeur
==> il y aura donc des modifications dans votre méthode createRooms.
Si vous n'avez pas une image pour chacun de vos lieux, vous pouvez en attendant de les trouver créer une image à partir d'un mot décrivant le lieu.
c) Parser : nouvelle version (à incorporer) qui n'a plus besoin de Scanner (pourquoi ?)
d) Game : sa majeure partie a été transférée dans GameEngine
e) GameEngine : reprend l'essentiel de l'ancienne classe Game (attention à l'affichage des messages et à processCommand qui devient interpretCommand et qui prend non plus une Command mais une String en paramètre car la méthode play a disparu au profit de l'interface graphique).
f) Attention à bien conserver la méthode printLocationInfo , en l'adaptant/complétant pour qu'elle affiche aussi l'image de la pièce. - Passons un peu plus de temps sur la classe UserInterface : c'est une nouvelle classe (à incorporer).
Utilisez la javadoc pour savoir à quoi servent les 5 classes commençant par J .
Pour vraiment comprendre le code de cette classe, il est fortement conseillé de dessiner (sur papier ou sur ordinateur) un schéma représentant les 3 composants graphiques affichés à un endroit précis de la fenêtre (vous avez dû essayer zuul-with-images, non ?), et d'y associer les morceaux de code correspondants.
Si vous ne comprenez pas quelque chose, vous pouvez demander des explications.
Votre jeu ne doit plus rien afficher dans la fenêtre Terminal de BlueJ (sauf debug et/ou messages d'erreur non destinés au joueur). - Intégrez cette nouvelle organisation dans votre jeu (sans régression bien sûr ! Il ne doit subsister aucun warning/avertissement !) .
Cette nouvelle conception vous permettra d'opter éventuellement par la suite pour une interface graphique plus élaborée (voir rubrique Plus de technique). - Pour mieux programmer le début de la classe UserInterface, remplacez chaque ligne import ... .*; par tous les imports de classes nécessaires.
Pour cela :
- mettre en commentaire une ligne import ... .*;
- recompiler pour que le compilateur ne trouve plus une certaine classe
- chercher Java 11 NomDeLaClasse dans google et cliquer sur le premier lien qui doit être la javadoc de cette classe
- noter le nom du paquetage tout en haut de la documentation et écrire l'instruction import en conséquence :
import paquetage.NomDeLaClasse;
- recompiler et suivre le processus précédent jusqu'à ce qu'il n'y ait plus d'erreur de compilation
- mettre en commentaire une nouvelle ligne import ... .*; et suivre le processus précédent jusqu'à ce que toutes ces lignes aient été remplacées.
S'il n'y a pas d'erreur de compilation lorsque vous commentez une ligne import ... .*; , c'est qu'elle ne sert à rien ! Supprimez-la.
Vous pouvez trouvez encore plus d'explications ici.
Cordialement
> Après plusieurs semaines à se poser la question avec mon binôme,
C'est beaucoup trop ! Vous devez poser la question sur ce forum au bout de 1 ou 2 jours maximum.
> on ne comprend toujours pas l'utilité de la dualité
Game/GameEngine tel que ces classes sont présentées dans
zuul_avec_images.
> En effet, il semble que GameEngine
ait littéralement aspiré tout ce que Game faisait et on ne retrouve dans
Game que quelques lignes.
> Personnellement je vois cette version de la classe Game comme un encapsulage inutile de GameEngine.
La différence essentielle avec la version précédente est la répartition des rôles entre GameEngine et UserInterface.
Game
ne sert plus alors qu'à créer ces 2 parties. Mais dans la suite, Game
devra créer un joueur, puis gérer les versions applette et application
de votre jeu.
> Pour le moment, nous avons pris la liberté de ne pas créer
de classe GameEngine. Faut-il absolument en créer une où est-ce
réellement sans importance ?
Compte tenu des explications
ci-dessus, cette classe doit être créée pour représenter ce qu'on
appelle dans beaucoup d'autres langages "le programme principal".
Un étudiant a écrit :
Bonjour monsieur.
Après avoir implémenté l' interface graphique dans zuul, j'ai un warning de compilation suivant:
"warning from last compilation enable(boolean) in java.awt.Component has been deprecated"
Savez d' ou pourrai venir se problème?
bonne journée.
1) une rapide recherche dans google ou dans un dictionnaire nous apprend que deprecated veut dire "obsolète"
2) le message vous précise qu'il s'agit de la méthode enable(boolean) de la classe Component
3) la javadoc de la classe Component dit : void
enable(boolean b)
Deprecated. As of JDK version 1.1, replaced by setEnabled(boolean)
.
Pour le savoir, il faut lire le code de cette méthode :
public void setGUI(UserInterface userInterface)
{
gui = userInterface;
printWelcome();
}
En la récrivant plus proprement, cela donne :
public void setGUI( final UserInterface pUserInterface )
{
this.aGui = pUserInterface;
this.printWelcome();
}
ce qui facilite la compréhension, j'espère que vous en conviendrez.
Son rôle est donc de mémoriser dans l'attribut gui du GameEngine, la UserInterface qu'on lui passe en paramètre, ce qui permettra ensuite au GameEngine d'appeler des méthodes sur la UserInterface. Accessoirement, elle appelle aussi printWelcome() pour bien débuter le jeu.
Un étudiant a écrit :
Bonjour monsieur,
1) "J'ai lu que ça pouvait concaténer plusieurs types d'objets."
C'est surtout fait pour concaténer des String, d'où son nom !
2) Bien que log ne soit pas un StringBuilder mais une TextArea, append fonctionne de la même manière en concaténant des String (ici, le texte à ré-afficher qui s'allonge à chaque commande tapée).
Un étudiant a écrit :
En
étudiant zuul_with_images, je me suis rendu compte dans la classe
GameEngine que l'on initialisait pas un attribut (le gui de type
UserInterface), je ne vois pas trop pourquoi et comment cela est
possible, si vous pouviez m'éclairer.
Vous n'avez pas vu la méthode setGUI qui initialise bien l'attribut gui.
Ensuite, il faut chercher où/quand elle est appelée. Peut-être dans la classe Game ?
Un étudiant a écrit :
Bonjour,
Je suis en train de faire les modifications nécessaires à mon jeu pour qu'il soit proche du projet zuul with images.
Cependant,
mes classes Game et UserInterface ne veulent pas compiler car elles
bloquent au même endroit c'est à dire au niveau de la procédure
printHelp de la classe GameEngine à la ligne:
aGui.println("Your command words are:"+ Parser.showCommands() );
En effet, il me signale non-static method showCommands() cannot be referenced from a static context.
Je ne comprends pas pourquoi...
Merci de votre réponse
Cordialement
Sur quoi appelez-vous la méthode showCommands ? Sur la classe Parser !? Donc le compilateur vous dit que cette méthode devrait être statique.
Par contre, il n'y a pas de raison que cette méthode soit statique puisque vous disposez d'une instance de la classe Parser ...
Veuillez également noter que le nom showCommands n'est plus adapté à cette méthode qui ne montre rien, mais qui retourne désormais une String ; getCommandList semble plus adapté dans ce cas.
Bonjour, dans la procédure createGUI() de la classe UserInterface de zuul-with-images, il y a ceci que je ne comprends pas :
myFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
Pouvez-vous l'expliquer ?
Merci
C'est tout à fait normal que vous ne compreniez pas cet extrait de code.
Il fait en sorte que fermer la fenêtre du jeu provoque bien l'arrêt du programme.
Cette syntaxe bizarre est équivalente à :
MyWindowAdapter vWA = new MyWindowAdapter();
myFrame.addWindowListener( vWA );
et
public class MyWindowAdapter extends WindowAdapter
{
@Override public void windowClosing( final WindowEvent pE )
{
System.exit( 0 );
} // windowClosing(.)
} // MyWindowAdapter
Pour tout comprendre, il vous faudra lire la javadoc des classes WindowListener et WindowAdapter, et des méthodes windowClosing(), et System.exit().
Je l'ai réécris ainsi:
WindowAdapter vWA = new WindowAdapter(){ public void windowClosing(WindowEvent pE) {System.exit(0);}};
myFrame.addWindowListener(vWA);
Je le comprends ainsi: on déclare une variable vWA de type WindowsAdapter, et cette variable stocke un WindowAdapter sur lequel la procédure windowClosing(.) est appelée lors de sa création.
Est-ce correct ?
Non !
Quel serait l'intérêt de terminer brutalement le programme à la création de l'objet WindowAdapter ???
Ici, on redéfinit la méthode (comme l'indiquait le @Override
que je vous avais précisé) pour expliquer au programme ce qu'il devra
faire quand on cliquera sur la croix de fermeture de la fenêtre.
Bonsoir,
Voici la méthode processCommand() de la classe UserInterface de Zuul-with-images:
/**
* A command has been entered. Read the command and do whatever is
* necessary to process it.
*/
private void processCommand()
{
boolean finished = false;
String input = entryField.getText();
entryField.setText("");
engine.interpretCommand(input);
}
La première instruction -en rouge- sert à quoi précisément ?
Car je ne vois pas son utilité...
Merci
Vous avez raison !
Cette ligne est une réminiscence de la version zuul-bad qui
permettait de sortir de la boucle d'exécution des commandes, mais qui
n'a plus lieu d'être dans cette version sans boucle dans processCommand.
Un étudiant a écrit :
bonjour,
Dans la classe UserInterface, la dernière ligne de commande ne marche pas
aEngine.interpretCommand(input);
cannot find symbol - method interpretCommand(java.lang.String)
L'erreur semble être que input est censé être un String mais n'en est pas un ...
Dans la même méthode on défini input par :
String input = entryField.getText();
input se référe donc a entryField.getText() or je ne sais pas ce que cet élément est ... Il y a beaucoup d'entryField dans le programme mais il y a un seul getText() ...
1)
"L'erreur semble être que input est censé être un String mais n'en est pas un ..." est un mauvais diagnostic puisque la déclaration "String input =..." montre bien que la variable input est une String.
Donc, si le compilateur ne trouve pas la méthode interpretCommand(java.lang.String), c'est que cette méthode n'a pas un paramètre de type String ou bien que vous avez mal orthographié son nom ... Dans les deux cas, il faut aller le vérifier dans la classe de cette méthode.
2)
"input se référe donc a entryField.getText() or je ne sais pas ce que cet élément est ..."
Il suffit de regarder la déclaration d'entryField
pour savoir de quelle classe elle est, puis d'aller voir dans la
javadoc de cette classe pour savoir ce que c'est et à quoi sert la
méthode getText().
3)
"Il y a beaucoup d'entryField dans le programme mais il y a un seul getText() ..."
Il n'y a qu'une seule déclaration de la variable entryField, plusieurs utilisations de cette variable, dont l'une consiste à appeler la méthode getText() sur l'objet dont la référence est stockée dans entryField.
Bonjour,
J'ai réalisé tous les changements, tout compile bien, et le jeu se lance.
Cependant, quand le jeu commence, la classe Userinterface se rouvre, et une phrase est surlignée :
URL imageURL = this.getClass().getClassLoader().getResource(imageName);
Et un message d'erreur apparaît :
java.lang.NullPointerException:
null(in sun.misc.MetaIndex)
Or le jeu marche correctement en dehors de ca. Qu'est-ce que cela signifie ?
1) Vous êtes-vous assurée qu' imageName ne valait pas null ?
2) Essayez en supprimant la partie .getClassLoader()
3) Si ça ne suffit pas, mettez le projet sur votre compte esiee et venez en 5356.
L'étudiante a répondu :
J'ai réussi a résoudre le problème.
- Regardez les attributs de la classe Room
- Regardez le constructeur de la classe Room
- Regardez la méthode createRooms dans GameEngine
- Si vous avez eu la bonne idée de conserver la méthode printLocationInfo, la méthode showImage doit y être appelée.
Sinon, showImage sera appelée 2 fois (au début et à chaque déplacement).
Un étudiant a écrit :
j'obtient se message d'erreur et n'arrive pas à résoudre le problème :
incompatible types: UserInterface cannot be converted to java.awt.event.ActionListener
à la ligne :
aentryField.addActionListener(this);
Un étudiant a écrit :
Bonjour Monsieur,
j'ai un problème, non gênant pour le programme mais plus esthétiquement.
En effet lorsque je change de salle un terminal s'affiche sans que je l'ai demandé, j'ai pourtant bien remplacé tous les System.out par des aGui, auriez-vous une idée d'où cela pourrait venir ?
Cordialement
Sans voir le programme, je dirais que vous avez conservé une ancienne version du Parser qui scanne directement le clavier, au lieu de scanner la String que la UserInterface a lu dans l'entryField.
Si ce n'est pas ça, mettez le projet sur votre compte esiee et venez en 5356.
Un étudiant a écrit :
J'ai intégré la nouvelle organisation de Zuul with images dans mon projet seulement j'ai une erreur de compilation que je ne comprends pas dans la méthode PrintHelp de la classe GameEngine j'ai écris :
L'erreur ne provient pas de la partie "Your command words are: " mais de la partie aParser.showCommands()
Pour que vous puissiez l'écrire après un +, il faut que ce soit une fonction qui retourne quelque chose ; or, le compilateur vous dit que cette méthode est void.
Il vous faut donc faire en sorte que cette méthode (en lui donnant un nom plus approprié) retourne une String contenant les commandes, plutôt qu'elle cherche à les afficher (comme on le faisait avant d'avoir une UserInterface).
Vous pourriez comprendre le problème :
- input est une String
- vous appelez interpretCommand en lui passant cette String
- alors que cette méthode attend un paramètre de type Command
Ce problème est probablement dû au fait que vous n'avez pas fait toutes les adaptations apportées par zuul-with-images, notamment la "nouvelle" méthode interpretCommand qui prend un paramètre de type String, et peut-être aussi le nouveau Parser.
Un étudiant a écrit :
Dans la classe GameEngine, faut-il garder la méthode printLocationInfo() ?
Un étudiant a écrit :
Si vous voulez que je puisse vous aider, il faut être plus précis :
1) "je n'arrive pas à lancer le jeu" : que se passe-t-il exactement ?
2) quelle ligne de code provoque le message d'erreur que vous indiquez ?
L'étudiant a répondu :
1) Je suppose que vous n'avez pas assez regardé le fonctionnement de zuul-with-images ou que vous n'avez pas compris son fonctionnement. Comment le jeu se lance-t-il ? Comment une ligne de texte tapée dans le champ de saisie finit par provoquer l'exécution de la commande qu'elle contient ?
2) Vous me répétez exactement ce que vous m'aviez indiqué dans votre question initiale !?
Si bouton.addActionListener est vraiment l'intégralité de la ligne de code, ce n'est pas étonnant qu'il y ait une erreur !
Il manque au moins qqch pour indiquer que c'est un appel de méthode et qqch pour indiquer la fin de l'instruction ...
Sinon, copiez/collez l'intégralité de la ligne de code qui provoque cette erreur !
Un étudiant a écrit :
Est-ce bien dans le but d'importer qu'une partie du package et pas le package en entier?
le compilateur compile et le jeu s’exécute, je ne comprends pas pourquoi, car si le compilateur compile, cela veut dire que cette ligne est "inutile".
1) oui, et aussi pour rendre explicite la liste des classes du JDK utilisées dans cette classe
2) oui, je ne crois pas qu'il y ait besoin d'une classe de ce paquetage ;
comme dit dans l'énoncé, supprimez tous les import, puis corrigez les erreurs en ajoutant à chaque fois la classe signalée en erreur
Bonjour,
En
modifiant les différentes classes( étape 2), certaines méthodes
(isUnknown, getCommandWord,hasSecondWord,getCommandList) empêchent le
programme de se compiler et l'erreur "cannot find symbol" apparait, j'ai
pourtant vérifié et ces méthodes existent bien dans CommandWord et
Command. Auriez vous une idée d'où vient le problème?
Oui, j'ai une idée d'où vient le problème : du code java que vous avez écrit pour appeler ces méthodes.
Par contre, comme vous ne me le fournissez pas, je ne peux pas vous en dire plus.
Le mieux serait de venir dans mon bureau après avoir mis votre jeu sur votre compte esiee (si ce n'est pas déjà le cas).
Sinon, envoyez-moi votre GameEngine.java par mail.
Réseaux sociaux